<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>OneDrive Explorer Sample</title>
  <link rel="stylesheet" type="text/css" href="style.css"/>
  <script type="text/javascript" src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
  <script id="odauth" src="odauth.js"></script>
  <link rel="icon" href="https://d.sfx-df.ms/images/favicon.ico" type="image/x-icon">
  <link rel="mask-icon" href="https://d.sfx-df.ms/images/mask_icon.svg" color="#094AB2">
  <script>
    function signInToOneDrive()
    {
      // Register your own application at https://apps.dev.microsoft.com
      // and set the "clientId" and "redirectUri" variables accordingly.
      var appInfo = {
        "clientId": "e9a57c07-69e4-41f5-b868-0f123d2fda17",
        "redirectUri": "http://localhost:9999/callback.html",
        "scopes": "user.read files.read files.read.all sites.read.all",
        "authServiceUri": "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"
      };
      provideAppInfo(appInfo);

      // use Microsoft Graph v1.0
      var baseUrl = getQueryVariable("baseUrl")
      msGraphApiRoot = (baseUrl) ? baseUrl : "https://graph.microsoft.com/v1.0/me";
      
      challengeForAuth();

      saveToCookie( { "apiRoot": msGraphApiRoot, "signedin": true } );
      return false;
    }

    function showCustomLoginButton(show)
    {
      var loginButton = document.getElementById("od-login");
      loginButton.style.display = show ? "block" : "none";

      var logoutButton = document.getElementById("od-logoff");
      logoutButton.style.display = show ? "none" : "block";
    }

    function getUrlParts(url)
    {
      var a = document.createElement("a");
      a.href = url;

      return { "hostname": a.hostname,
               "path": a.pathname }
    }

    function setOneDriveTitle(title)
    {
        var element = document.getElementById("od-site");
        element.innerText = title;
    }


    function saveToCookie(obj)
    {
      var expiration = new Date();
      expiration.setTime(expiration.getTime() + 3600 * 1000);
      var data = JSON.stringify(obj);
      var cookie = "odexplorer=" + data +"; path=/; expires=" + expiration.toUTCString();

      if (document.location.protocol.toLowerCase() == "https") {
        cookie = cookie + ";secure";
      }
      document.cookie = cookie;
    }

    function loadFromCookie()
    {
      var cookies = document.cookie;
      var name = "odexplorer=";
      var start = cookies.indexOf(name);
      if (start >= 0) {
        start += name.length;
        var end = cookies.indexOf(';', start);
        if (end < 0) {
          end = cookies.length;
        }
        else {
          postCookie = cookies.substring(end);
        }

        var value = cookies.substring(start, end);
        return JSON.parse(value);
      }

      return "";
    }

    function signOut()
    {
      logoutOfAuth();
      saveToCookie( { "apiRoot": msGraphApiRoot, "signedin": false } );
      $('#od-breadcrumb').empty();
      $('#od-items').empty();
      $('#od-json').empty();
      location.reload();
    }

    function getQueryVariable(variable)
    {
       var query = window.location.search.substring(1);
       var vars = query.split("&");
       for (var i=0;i<vars.length;i++) {
               var pair = vars[i].split("=");
               if(pair[0] == variable){return pair[1];}
       }
       return(false);
     }
  </script>
</head>
<body>
  <div id="od-site">
    <div id="od-commands">
      <div id="od-login" style="display: hidden">
        <a href="#" onclick="signInToOneDrive()">Sign in to OneDrive</a>&nbsp;&nbsp;
      </div>
      <div id="od-logoff" style="display: hidden">
        <a href="#" onclick="signOut()">Sign Out</a>
      </div>
    </div>
    <div id="od-title">OneDrive Explorer Sample - JS</div>
  </div>
  
  <div id="od-loading"></div>
  <div id="od-breadcrumb"></div>
  <div id="od-content">
    <div id="od-items" class="od-pagecol"></div>
    <div id="od-json" class="od-pagecol"></div>
  </div>
  <script>
    var baseUrl = getQueryVariable("baseUrl")
    msGraphApiRoot = (baseUrl) ? baseUrl : "https://graph.microsoft.com/v1.0/me";

    var data = loadFromCookie();
    if (data)
    {
      if (!baseUrl)
        msGraphApiRoot = data.apiRoot;
      showCustomLoginButton(!data.signedin)
    }

    // we use the url fragment to specify the file path within onedrive
    // (eg. #/pictures/foo.jpg), so we bind to the hashchange event to
    // know when it changes. in cases where we change the hash from
    // within this app due to a user click, we call odauth ourselves and
    // pre-set loadedFromHash to the new value so that this handler doesn't
    // call odauth() again. this is so that we handle the auth popup properly.
    // odauth can either be called in response to a user click (in which)
    // case it's allowed to pop up an auth dialog, or with no user click,
    // in which case it's only allowed to show a 'sign-in' button (if it
    // tried to pop up a window, most browsers' popup blockers would block it).
    // this handler needs to call odauth in non-click mode since it doesn't
    // know why the hash changed.
    var loadedForHash = "";
    $(window).bind('hashchange', function() {
      if (window.location.hash != loadedForHash) {
        loadedForHash = window.location.hash;
        odauth();
      }

     return false;
    });

    // we bind to jquery's ajax start/stop events so that we can style the
    // page differently when a network call is being made
    $(document).on({
      ajaxStart: function() {$('body').addClass('loading');},
      ajaxStop:  function() {$('body').removeClass('loading');}
    });

    // based on http://jsfiddle.net/KJQ9K/554/
    function syntaxHighlight(obj) {
      var json = JSON.stringify(obj, undefined, 2)
      json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
      return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g,
        function (match) {
          var cls = 'number';
          if (/^"/.test(match)) {
            if (/:$/.test(match)) {
              cls = 'key';
            } else {
              cls = 'string';
            }
          } else if (/true|false/.test(match)) {
            cls = 'boolean';
          } else if (/null/.test(match)) {
            cls = 'null';
          }
          return '<span class="' + cls + '">' + match + '</span>';
        });
    }

    // called to update the breadcrumb bar at the top of the page
    function updateBreadcrumb(decodedPath) {
      var path = decodedPath || '';
      $('#od-breadcrumb').empty();
      var runningPath = '';
      var segments = path.split('/');
      for (var i = 0 ; i < segments.length; i++) {
        if (i > 0) {
          $('<span>').text(' > ').appendTo("#od-breadcrumb");
        }

        var segment = segments[i];
        if (segment) {
          runningPath = runningPath + '/' + encodeURIComponent(segment);
        } else {
          segment = 'Files';
        }

        $('<a>').
          attr("href", "#" + runningPath).
          click(function() {
            // when the page changes in response to a user click,
            // we set loadedForHash to the new value and call
            // odauth ourselves in user-click mode. this causes
            // the catch-all hashchange event handler not to
            // process the page again. see comment at the top.
            loadedForHash = $(this).attr('href');
            window.location = loadedForHash;
            odauth(true);
          }).
          text(segment).
          appendTo("#od-breadcrumb");
      }
    }

    // odauth calls our onAuthenticated method to give us the user's auth token.
    // in this demo app we just use this as the method to drive the page logic
    function onAuthenticated(token, authWindow) {
      if (token) {
        if (authWindow) {
          removeLoginButton();
          authWindow.close();
        }

        (function($){
          // we extract the onedrive path from the url fragment and we
          // flank it with colons to use the api's path-based addressing scheme
          var path = "";
          var beforePath = "";
          var afterPath = "";
          if (window.location.hash.length > 1) {
            path = window.location.hash.substr(1);
            beforePath =":";
            afterPath = ":";
          }

          var odurl = msGraphApiRoot + "/drive/root" + beforePath + path + afterPath;

          // the expand and select parameters mean:
          //  "for the item i'm addressing, include its thumbnails and children,
          //   and for each of the children, include its thumbnails. for those
          //   thumbnails, return the 'large' size"
          var thumbnailSize = "large"
          var odquery = "?expand=thumbnails,children(expand=thumbnails(select=" + thumbnailSize + "))";

          $.ajax({
            url: odurl + odquery,
            dataType: 'json',
            headers: { "Authorization": "Bearer " + token },
            accept: "application/json;odata.metadata=none",
            success: function(data) {
              if (data) {
                // clear out the old content
                $('#od-items').empty();
                $('#od-json').empty();

                // add the syntax-highlighted json response
                $("<pre>").html(syntaxHighlight(data)).appendTo("#od-json");

                // process the response data. if we get back children (data.children)
                // then render the tile view. otherwise, render the "one-up" view
                // for the item's individual data. we also look for children in
                // 'data.value' because if this app is ever configured to reqeust
                // '/children' directly instead of '/parent?expand=children', then
                // they'll be in an array called 'data'
                var decodedPath = decodeURIComponent(path);
                document.title = "OneDrive Explorer" + ((decodedPath.length > 0) ? " - " + decodedPath : "");
                  
                updateBreadcrumb(decodedPath);
                var children = data.children || data.value;
                if (children && children.length > 0) {
                  $.each(children, function(i,item) {
                    var tile = $("<div>").
                      attr("href", "#" + path + "/" + encodeURIComponent(item.name)).
                      addClass("item").
                      click(function() {
                        // when the page changes in response to a user click,
                        // we set loadedForHash to the new value and call
                        // odauth ourselves in user-click mode. this causes
                        // the catch-all hashchange event handler not to
                        // process the page again. see comment at the top.
                        loadedForHash = $(this).attr('href');
                        window.location = loadedForHash;
                        odauth(true);
                      }).
                      appendTo("#od-items");

                    // look for various facets on the items and style them accordingly
                    if (item.folder) {
                      tile.addClass("folder");
                    }
                    if (item.file) {
                      tile.addClass("file");
                    }

                    if (item.thumbnails && item.thumbnails.length > 0) {
                      var container = $("<div>").attr("class", "img-container").appendTo(tile)
                      $("<img>").
                        attr("src", item.thumbnails[0][thumbnailSize].url).
                        appendTo(container);
                    }

                    $("<div>").
                      addClass("nameplate").
                      text(item.name).
                      appendTo(tile);
                  });
                }
                else if (data.file) {
                  // 1-up view
                  var tile = $("<div>").
                    addClass("item").
                    addClass("oneup").
                    appendTo("#od-items");

                  var downloadUrl = data['@microsoft.graph.downloadUrl'];
                  if (downloadUrl) {
                    tile.click(function(){window.open(downloadUrl, "Download");});
                  }

                  if (data.folder) {
                    tile.addClass("folder");
                  }

                  if (data.thumbnails && data.thumbnails.length > 0) {
                    $("<img>").
                      attr("src", data.thumbnails[0].large.url).
                      appendTo(tile);
                  }
                }
                else {
                  $('<p>No items in this folder.</p>').appendTo('#od-items');  
                }
              } else {
                $('#od-items').empty();
                $('<p>error.</p>').appendTo('#od-items');
                $('#od-json').empty();
              }
            }
          });
        })(jQuery);
      }
      else {
        alert("Error signing in");
      }
    }

    // start the whole thing off by calling odauth() in non-click mode.
    // if the user isn't logged in already, a sign-in link will appear
    // for them to click.
    odauth();
  </script>
</body>
</html>
